#!/bin/sh

# Posix shell function for finding executable files in the $PATH

# Copyright 2016-2022 orbea
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

set -euf

exists () {
  ALLMATCHES=
  while [ $# -gt 0 ]; do
    case "$1" in
      -- ) shift; break ;;
      -a|--all ) ALLMATCHES=1; shift ;;
      -h|--help ) printf %s\\n "usage: $0 [-a] command [arg ...]"; exit 0 ;;
      -* ) printf %s\\n "$0: Illegal option $1" >&2; exit 1 ;;
      * ) break ;;
    esac
  done

  r=0; cwd="$(pwd)"
  while [ $# -gt 0 ]; do
    v=1; arg="$1"; shift
    case "$arg" in
      ''|*/ )
        :
      ;;
      /* )
        if [ -f "$arg" ] && [ -x "$arg" ]; then
          printf %s\\n "$arg"
          v=0
        fi
      ;;
      ./* )
        if [ -f "$arg" ] && [ -x "$arg" ]; then
          pre="$(cd -- "${arg%%/*}/" && pwd)"
          printf %s\\n "${pre%/}/$arg"
          v=0
        fi
      ;;
      */* )
        if [ -f "$arg" ] && [ -x "$arg" ]; then
          printf %s\\n "$(cd -- "${arg%%/*}/.." && pwd)/$arg"
          v=0
        fi
      ;;
      * )
        if [ -n "${PATH+x}" ]; then
          p=":${PATH:-$cwd}"
          while [ "$p" != "${p#*:}" ] && [ -n "${p#*:}" ]; do
            p="${p#*:}"; x="${p%%:*}"; z="${x:-$cwd}"; d="${z%/}/$arg"
            if [ -f "$d" ] && [ -x "$d" ]; then
              case "$d" in
                /* ) : ;;
                ./* ) pre="$(cd -- "${d%/*}/" && pwd)"; d="${pre%/}/$d" ;;
                * ) d="$(cd -- "${d%/*}/" && pwd)/$arg" ;;
              esac
              printf %s\\n "$d"
              v=0
              [ -n "${ALLMATCHES}" ] || break
            fi
          done
        fi
      ;;
    esac
    [ $v = 0 ] || r=1
  done
  return $r
}

if [ -n "${1+x}" ]; then
  exists "${@:-}"
else
  exists
fi
